﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Function_Analyzer.MathUtil
{
    public class KhoiPhucSo
    {
        const int ROUND_NUM = 6;
        const int muc=1;  //1,2

        int mucKhoiPhuc = 10 * (muc * 2 - 1);
        public int MucKhoiPhuc
        {
            get
            {
                return this.mucKhoiPhuc;
            }
            set
            {
                this.mucKhoiPhuc = value;
            }
        }
        //'************************KHOI PHUC SO DUNG********************************
        //'Co kha nang khoi phuc ket qua da tinh ve dang pi, ln, can bac 2 va phan so voi gioi han phuc hoi tuy chon
        //'************************************************************************

        public string FixVal(double num)
        {
            return FixVal(num.ToString(), true);
        }

        public string FixVal(string st)
        {
            return FixVal(st, true);
        }

        public string FixVal(string st, bool enableOptimized)
        {
            string rs="";
            if (st == "Error") st = "#";
            if (!Util.IsNumericStr(st)) return st;

            double num = Convert.ToDouble(st);
            if (num == 0 || num == Math.Floor(num) || !enableOptimized) goto koxet;

            //rut bieu thuc cap 2
            int j;
            bool chia=false;
            string kq;
            for(j=1;j<mucKhoiPhuc;j++){
                //=================================rut bt cap 1 loai chia 2 nhu (-1+2*[2]7)/2
                double n=num*j;
                chia=true;
                //xet pi
                for(int i=0;i<mucKhoiPhuc;i++){
                    kq=RutPi(n+i);
                    if(!Util.IsNumericStr(kq)){
                        rs="-"+i+"+"+kq;
                        goto rutgon;
                    }
                    kq=RutPi(n - i);
                    if (!Util.IsNumericStr(kq))
                    {
                        rs = i + "+" + kq;
                        goto rutgon;
                    }
                }

                //xet can bac 2
                for (int i = 0; i < mucKhoiPhuc; i++)
                {
                    kq = RutCan(n + i);
                    if (!Util.IsNumericStr(kq))
                    {
                        rs = "-" + i + "+" + kq;
                        goto rutgon;
                    }
                    kq = RutCan(n - i);
                    if (!Util.IsNumericStr(kq))
                    {
                        rs = i + "+" + kq;
                        goto rutgon;
                    }
                }

                //xet ln
                for (int i = 0; i < mucKhoiPhuc; i++)
                {
                    kq = RutLn(n + i);
                    if (!Util.IsNumericStr(kq))
                    {
                        rs = "-" + i + "+" + kq;
                        goto rutgon;
                    }
                    kq = RutLn(n - i);
                    if (!Util.IsNumericStr(kq))
                    {
                        rs = i + "+" + kq;
                        goto rutgon;
                    }
                }

                //xet phan so
                int k = mucKhoiPhuc;
                do{
                    double x = Math.Round(n * k, 4);
                    if (x != 0)
                    {
                        if (x == Math.Floor(x))
                        {
                            rs= RutGonPhanSo((int)x, k);
                            goto rutgon;
                        }
                    }
                    else rs = "0";
                    k--;
                } while (k >= 2);

                //=================================rut bt cap 1 loai nhan 2 nhu (-1+2*[2]7)*2
                n = num / j;
                chia = false;
                //xet pi
                for (int i = 0; i < mucKhoiPhuc; i++)
                {
                    kq = RutPi(n + i);
                    if (!Util.IsNumericStr(kq))
                    {
                        rs = "-" + i + "+" + kq;
                        goto rutgon;
                    }
                    kq = RutPi(n - i);
                    if (!Util.IsNumericStr(kq))
                    {
                        rs = i + "+" + kq;
                        goto rutgon;
                    }
                }

                //xet can bac 2
                for (int i = 0; i < mucKhoiPhuc; i++)
                {
                    kq = RutCan(n + i);
                    if (!Util.IsNumericStr(kq))
                    {
                        rs = "-" + i + "+" + kq;
                        goto rutgon;
                    }
                    kq = RutCan(n - i);
                    if (!Util.IsNumericStr(kq))
                    {
                        rs = i + "+" + kq;
                        goto rutgon;
                    }
                }

                //xet ln
                for (int i = 0; i < mucKhoiPhuc; i++)
                {
                    kq = RutLn(n + i);
                    if (!Util.IsNumericStr(kq))
                    {
                        rs = "-" + i + "+" + kq;
                        goto rutgon;
                    }
                    kq = RutLn(n - i);
                    if (!Util.IsNumericStr(kq))
                    {
                        rs = i + "+" + kq;
                        goto rutgon;
                    }
                }

                //xet phan so
                k = mucKhoiPhuc;
                do
                {
                    double x = Math.Round(n * k, 4);
                    if (x != 0)
                    {
                        if (x == Math.Floor(x))
                        {
                            rs = RutGonPhanSo((int)x, k);
                            goto rutgon;
                        }
                    }
                    else rs = "0";
                    k--;
                } while (k >= 2);
            }

        rutgon:
            if (j != 1)
            {
                if (chia) rs = "(" + rs + ")/" + j;
                else rs = "(" + rs + ")*" + j;
            }

            rs = rs.Replace("-0+", "");
            rs = rs.Replace("0+", "");
            //xu ly dau
            rs = rs.Replace("-+", "-");
            rs = rs.Replace("+-", "-");
            //xu ly so 1
            rs = rs.Replace("-1*", "-");
            rs = rs.Replace("+1*", "+");
            rs = rs.Replace("(1*", "(");
            if(rs.Substring(0,2)=="1*") rs = rs.Substring(2);
            //khao sat 0*
            if ((rs.Contains("+0*") || rs.Contains("-0*") || rs.Contains("(0*") || rs[0] == '0') && Convert.ToDouble(rs) == 0) rs = "0";
            rs = rs.Replace("+0*pi", "");
            rs = rs.Replace("-0*pi", "");
            return rs;

        koxet:
            return Math.Round(num, ROUND_NUM).ToString();
        }

        private string RutPi(double n)
        {
            int i = mucKhoiPhuc;
            do{
                double x = Math.Round(n / Math.PI * i, ROUND_NUM);
                if(x==Math.Floor(x)){
                    return RutGonPhanSo((int)x, i, "pi", true);
                }
                i--;
            }while(i>=2);
            return n.ToString();
        }

        private string RutCan(double n)
        {
            int i = 2;
            do
            {
                double x = Math.Round(n / Math.Sqrt(i), ROUND_NUM);
                if (x == Math.Floor(x))
                {
                    return x + "[2]" + i;
                }
                i++;
            } while (i <= mucKhoiPhuc);
            return n.ToString();
        }

        private string RutLn(double n)
        {
            int i = mucKhoiPhuc;
            do
            {
                double x = Math.Round(n / Math.Log(i), ROUND_NUM);
                if (x == Math.Floor(x))
                {
                    return x + "*ln(" + i+")";
                }
                i--;
            } while (i >=2);
            return n.ToString();
        }

        //'******************sua lai cho nay*******************
        private string RutGonPhanSo(double a, double b)
        {
            return RutGonPhanSo(a, b, "", true);
        }

        private string RutGonPhanSo(double a, double b, string dau, bool tren_tu)
        {
            int i = mucKhoiPhuc;
            do
            {
                double c = a / i;
                double d = b / i;
                if (c == Math.Floor(c) && d == Math.Floor(d))
                {
                    //chi co dau moi co mau so =1
                    if (dau != "")
                    {
                        if (d == 1)
                        {
                            if (tren_tu) return c + "*" + dau;
                            else return c + "/" + dau;
                        }
                        else
                        {
                            if (tren_tu) return c + "*" + dau + "/" + d;
                            else return c + "/(" + d + "*" + dau + ")";
                        }
                    }
                    else return c + "/" + d;
                }
                i--;
            } while (i >= 2);
            if (dau != "") return a + "*" + dau + "/" + b;
            else return a + "/" + b;
        }
    }
}
